<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>SPI</title>
<title>CMSIS-Driver Implementations: SPI</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="cmsis.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="printComponentTabs.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
  $(window).load(resizeHeight);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 46px;">
  <td id="projectlogo"><img alt="Logo" src="CMSIS_Logo_Final.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">CMSIS-Driver Implementations
   &#160;<span id="projectnumber">Version 2.6.1</span>
   </div>
   <div id="projectbrief">MCU independent device driver implementations and template files of the CMSIS-Driver API specification</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<div id="CMSISnav" class="tabs1">
    <ul class="tablist">
      <script type="text/javascript">
		<!--
		writeComponentTabs.call(this);
		//-->
      </script>
	  </ul>
</div>
<!-- Generated by Doxygen 1.8.6 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Usage&#160;and&#160;Description</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('driver_SPI.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">SPI </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>The SPI MultiSlave wrapper (SPI_MultiSlave.c) resides on top of an arbitrary SPI CMSIS-Driver and exports a maximum of four SPI CMSIS-Drivers with SPI Master functionality only. Slave functionalities are disabled and calling the slave functions will return with an error. An SPI slave device connects to one of the exported drivers and uses it as any other SPI CMSIS-Driver (in master mode only). The wrapper provides multi thread protection.</p>
<p>Each slave can use a different bus configuration. The MultiSlave wrapper will detect which slave device is addressed by a particular function call and reconfigures the SPI bus accordingly. When using the SPI MultiSlave wrapper, the slave select mode must always be configured as <code>ARM_SPI_SS_MASTER_UNUSED</code>, since the underlying bus controlling the SPI driver can only control one slave select line at the time. The slave select line for each particular slave device is instead controlled by the MultiSlave wrapper using the function SPI_Control_SlaveSelect that must be implemented in the user application. A function prototype can be found in the SPI_Multislave.h header file and must be included in the project.</p>
<p>When called from different threads, the MultiSlave wrapper can be busy (if any data transfer is in progress). In such a case, transfer operations will be queued and executed immediately after the current transfer completes. The transfer queue operates as a FIFO, so transfers will be executed in the same call order as expected by the application.</p>
<p>The wrapper is configured using the SPI_MultiSlave_Config.h file, which contains the following options:</p>
<ul>
<li><code>#define</code> <code>SPI_DRIVER</code> specifies the underlying SPI CMSIS-Driver, which actually controls the SPI peripheral and the accesses the bus. The wrapper will connect to that driver.</li>
<li><code>#define</code> <code>SPI_ENABLE_SLAVE_x</code> enables each SPI bus connected slave. This basically means that the driver control block Driver_SPIn will be exported by the wrapper for each particular slave.</li>
<li><code>#define</code> <code>SPI_DRIVER_SLAVE_x</code> sets the exported control block number n, for example Driver_SPIn. The application connects to this driver.</li>
</ul>
<p><b>Code example</b></p>
<p>This is a demo application which demonstrates the usage of the SPI MultiSlave driver wrapper. It consists of two threads that periodically access two SPI slave devices.</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;string.h&gt;</span></div>
<div class="line"><span class="preprocessor">#include &quot;cmsis_os2.h&quot;</span></div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#include &quot;RTE_Components.h&quot;</span></div>
<div class="line"><span class="preprocessor">#include  CMSIS_device_header</span></div>
<div class="line"><span class="preprocessor"></span><span class="preprocessor">#include &quot;stm32f2xx_hal.h&quot;</span>              <span class="comment">// Keil::Device:STM32Cube HAL:Common</span></div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#include &quot;SPI_MultiSlave.h&quot;</span>             <span class="comment">// Keil::CMSIS Driver:SPI:Multi-Slave</span></div>
<div class="line"> </div>
<div class="line"><span class="comment">/* Thread prototypes */</span></div>
<div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> Thread_A (<span class="keywordtype">void</span> *argument);</div>
<div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> Thread_B (<span class="keywordtype">void</span> *argument);</div>
<div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> app_main (<span class="keywordtype">void</span> *argument);</div>
<div class="line"> </div>
<div class="line"><span class="comment">/* A and B Thread IDs */</span></div>
<div class="line"><span class="keyword">static</span> osThreadId_t ThreadId_A;</div>
<div class="line"><span class="keyword">static</span> osThreadId_t ThreadId_B;</div>
<div class="line"> </div>
<div class="line"><span class="comment">/* SPI A Driver, controls Slave Device 0, uses underlying Driver_SPI1 (see SPI_MultiSlaveConfig.h) */</span></div>
<div class="line"><span class="keyword">extern</span> ARM_DRIVER_SPI         Driver_SPI10;</div>
<div class="line"><span class="preprocessor">#define SPI_A               (&amp;Driver_SPI10)</span></div>
<div class="line"><span class="preprocessor"></span> </div>
<div class="line"><span class="comment">/* SPI B Driver, controls Slave Device 1, uses underlying Driver_SPI1 (see SPI_MultiSlaveConfig.h) */</span></div>
<div class="line"><span class="keyword">extern</span> ARM_DRIVER_SPI         Driver_SPI11;</div>
<div class="line"><span class="preprocessor">#define SPI_B               (&amp;Driver_SPI11)</span></div>
<div class="line"><span class="preprocessor"></span> </div>
<div class="line"><span class="keywordtype">void</span> SPI_Control_SlaveSelect (uint32_t device, uint32_t ss_state) {</div>
<div class="line">  GPIO_TypeDef* GPIOx;</div>
<div class="line">  uint16_t pin;</div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">if</span> (device == 0) {</div>
<div class="line">    <span class="comment">/* Select Device 0 SS pin (SPI_A) */</span></div>
<div class="line">    GPIOx = GPIOE;</div>
<div class="line">    pin   = GPIO_PIN_0;</div>
<div class="line">  }</div>
<div class="line">  <span class="keywordflow">else</span> {</div>
<div class="line">    <span class="comment">/* Select Device 1 SS pin (SPI_B) */</span></div>
<div class="line">    GPIOx = GPIOE;</div>
<div class="line">    pin   = GPIO_PIN_15;</div>
<div class="line">  }</div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">if</span> (ss_state == ARM_SPI_SS_INACTIVE) {</div>
<div class="line">    <span class="comment">/* Set GPIO pin high */</span></div>
<div class="line">    HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_SET);</div>
<div class="line">  } <span class="keywordflow">else</span> {</div>
<div class="line">    <span class="comment">/* Set GPIO pin low */</span></div>
<div class="line">    HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_RESET);</div>
<div class="line">  }</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="comment">/*----------------------------------------------------------------------------</span></div>
<div class="line"><span class="comment"> * SPI Thread A</span></div>
<div class="line"><span class="comment"> *---------------------------------------------------------------------------*/</span></div>
<div class="line">__NO_RETURN <span class="keyword">static</span> <span class="keywordtype">void</span> Thread_A (<span class="keywordtype">void</span> *argument) {</div>
<div class="line">  <span class="keywordtype">char</span> *p = <span class="stringliteral">&quot;Sending data to Slave Device 0&quot;</span>;</div>
<div class="line">  (void)argument;</div>
<div class="line">  </div>
<div class="line">  SPI_A-&gt;Initialize(NULL);</div>
<div class="line">  SPI_A-&gt;PowerControl(ARM_POWER_FULL);</div>
<div class="line">  SPI_A-&gt;Control(ARM_SPI_MODE_MASTER | ARM_SPI_CPOL0_CPHA0  \</div>
<div class="line">                                     | ARM_SPI_DATA_BITS(8) \</div>
<div class="line">                                     | ARM_SPI_MSB_LSB      \</div>
<div class="line">                                     | ARM_SPI_SS_MASTER_UNUSED,</div>
<div class="line">                                     10000000);</div>
<div class="line"> </div>
<div class="line">  SPI_A-&gt;Control(ARM_SPI_SET_DEFAULT_TX_VALUE, 0xFF);</div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">while</span>(1) {</div>
<div class="line">    <span class="comment">/* Send to Slave Device 0 */</span></div>
<div class="line">    SPI_A-&gt;Send(p, strlen(p));</div>
<div class="line"> </div>
<div class="line">    osDelay(10);</div>
<div class="line">  }</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="comment">/*----------------------------------------------------------------------------</span></div>
<div class="line"><span class="comment"> * SPI Thread B</span></div>
<div class="line"><span class="comment"> *---------------------------------------------------------------------------*/</span></div>
<div class="line">__NO_RETURN <span class="keyword">static</span> <span class="keywordtype">void</span> Thread_B (<span class="keywordtype">void</span> *argument) {</div>
<div class="line">  <span class="keywordtype">char</span> *p = <span class="stringliteral">&quot;Sending data to Slave Device 1&quot;</span>;</div>
<div class="line">  (void)argument;</div>
<div class="line"> </div>
<div class="line">  <span class="comment">/* Initialize and configure SPI */</span></div>
<div class="line">  SPI_B-&gt;Initialize(NULL);</div>
<div class="line">  SPI_B-&gt;PowerControl(ARM_POWER_FULL);</div>
<div class="line">  SPI_B-&gt;Control(ARM_SPI_MODE_MASTER | ARM_SPI_CPOL1_CPHA1  \</div>
<div class="line">                                     | ARM_SPI_DATA_BITS(8) \</div>
<div class="line">                                     | ARM_SPI_MSB_LSB      \</div>
<div class="line">                                     | ARM_SPI_SS_MASTER_UNUSED,</div>
<div class="line">                                     15000000);</div>
<div class="line"> </div>
<div class="line">  SPI_B-&gt;Control(ARM_SPI_SET_DEFAULT_TX_VALUE, 0xFF);</div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">while</span>(1) {</div>
<div class="line">    <span class="comment">/* Send to Slave Device 1 */</span></div>
<div class="line">    SPI_B-&gt;Send(p, strlen(p));</div>
<div class="line"> </div>
<div class="line">    osDelay(10);</div>
<div class="line">  }</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="comment">/*----------------------------------------------------------------------------</span></div>
<div class="line"><span class="comment"> * Application main thread</span></div>
<div class="line"><span class="comment"> *---------------------------------------------------------------------------*/</span></div>
<div class="line">__NO_RETURN <span class="keyword">static</span> <span class="keywordtype">void</span> app_main (<span class="keywordtype">void</span> *argument) {</div>
<div class="line">  (void)argument;</div>
<div class="line"> </div>
<div class="line">  <span class="comment">/* Create SPI threads */</span></div>
<div class="line">  ThreadId_A = osThreadNew(Thread_A, NULL, NULL);</div>
<div class="line">  ThreadId_B = osThreadNew(Thread_B, NULL, NULL);</div>
<div class="line"> </div>
<div class="line">  osDelay(osWaitForever);</div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">for</span> (;;) {}</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">int</span> main (<span class="keywordtype">void</span>) {</div>
<div class="line">  </div>
<div class="line">  <span class="comment">// System Initialization</span></div>
<div class="line">  SystemCoreClockUpdate();</div>
<div class="line"> </div>
<div class="line">  osKernelInitialize();                 <span class="comment">// Initialize CMSIS-RTOS</span></div>
<div class="line">  osThreadNew(app_main, NULL, NULL);    <span class="comment">// Create application main thread</span></div>
<div class="line">  osKernelStart();                      <span class="comment">// Start thread execution</span></div>
<div class="line">  <span class="keywordflow">for</span> (;;) {}</div>
<div class="line">}</div>
</div><!-- fragment --> </div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated on Mon Jul 13 2020 11:25:48 for CMSIS-Driver Implementations by Arm Ltd. All rights reserved.
	<!--
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.6 
	-->
	</li>
  </ul>
</div>
</body>
</html>
